package com.ylr.base.common.factory;

import com.ylr.base.common.po.user.UserPo;
import com.ylr.base.common.utils.UserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.TaskDecorator;

import java.util.Objects;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-08 21:42:04
 * className: YlrThreadFactory
 * version: 1.0
 * description:
 */
public class YlrThreadFactory implements ThreadFactory {

    private final String threadNamePrefix;

    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);

    public YlrThreadFactory(String threadNamePrefix) {
        this.threadNamePrefix = threadNamePrefix;
        SecurityManager s = System.getSecurityManager();
        this.group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                threadNamePrefix + threadNumber.getAndIncrement(),
                0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        // 设置异常处理类
        t.setUncaughtExceptionHandler(new ThreadUncaughtExceptionHandler());
        return t;
    }

    /**
     * 线程异常处理类
     */
    private static class ThreadUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

        private static final Logger log = LoggerFactory.getLogger(ThreadUncaughtExceptionHandler.class);

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            log.error("线程（{}）执行异常。message={} class={}", t.getName(), e.getMessage(), e.getClass(), e);
        }
    }

    /**
     * 创建线程装饰器对象
     */
    public static TaskDecorator getTaskDecorator() {
        return runnable -> {
            // 获取父线程的链路追踪配置
//            Map<String, String> map = MDC.getCopyOfContextMap();
            // 获取调用线程存储的请求用户数据
            UserPo userPo = UserUtils.getUser();
            return () -> {
                try {
                    // 设置子线程链路追踪配置
//                    MDC.setContextMap(map);
                    // 设置请求用户
                    UserUtils.setUser(userPo);
                    // 运行目标线程
                    runnable.run();
                } finally {
                    // 清理子线程的链路追踪配置
//                    MDC.clear();
                    // 清理请求用户
                    UserUtils.deleteUser();
                }
            };
        };
    }

    /**
     * 根据配置文件配置的任务拒绝策略数值，创建对应的任务拒绝策略对象
     */
    public static RejectedExecutionHandler getRejectedExecutionHandler(Integer rejectType) {
        if (Objects.isNull(rejectType)) {
            rejectType = 0;
        }
        RejectedExecutionHandler policy;
        switch (rejectType) {
            case 1:
                policy = new ThreadPoolExecutor.AbortPolicy();
                break;
            case 2:
                policy = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case 3:
                policy = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case 0:
            default:
                policy = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
        }
        return policy;
    }
}

